package licode.unisop.single.platform.infrastructure.repository.dao;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import licode.unisop.provider.info.PlatPageInfo;
import licode.unisop.provider.info.SiPlatIdFind;
import licode.unisop.provider.info.SiPlatRealmUpdateIn;
import licode.unisop.provider.utils.StrUtil;
import licode.unisop.provider.vo.SiPageResult;
import licode.unisop.provider.vo.SiPlatform;
import licode.unisop.single.platform.application.entity.PlatformEntity;
import licode.unisop.single.platform.application.gateway.PlatformDao;
import licode.unisop.single.platform.infrastructure.assembler.UniPlatformSingleAssembler;
import licode.unisop.single.platform.infrastructure.repository.mapper.UniPlatformMapper;
import licode.unisop.single.platform.infrastructure.repository.po.AuthPlatformPO;
import licode.unisop.single.platform.infrastructure.repository.po.PlatformPO;
import licode.unisop.single.platform.infrastructure.utils.PageUtil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * uni-platform-single
 *
 * @author licode
 * @date 2016-08-27 18:14:10
 */
@Component
public class PlatformDaoImpl
        extends MPJBaseServiceImpl<UniPlatformMapper, PlatformPO>
        implements PlatformDao {
    @Resource
    private UniPlatformSingleAssembler uniPlatformSingleAssembler;

    @Override
    public void add(PlatformEntity item) {
        item.setUpdateTime(LocalDateTime.now());
        super.save(uniPlatformSingleAssembler.fromPlatformEntity(item));
    }

    @Override
    public void update(PlatformEntity item) {
        super.updateById(uniPlatformSingleAssembler.fromPlatformEntity(item));
    }

    @Override
    public void removeWithId(Serializable id) {
        super.removeById(id);
    }

    @Override
    public void updatePlatformRealm(SiPlatRealmUpdateIn platform) {
        if (platform.getPlatformId() != null) {
            super.lambdaUpdate()
                    .set(PlatformPO::getRealmId, platform.getRealmId())
                    .eq(PlatformPO::getId, platform.getPlatformId())
                    .update();
        }
    }

    @Override
    public PlatformEntity getWithId(Serializable id) {
        return uniPlatformSingleAssembler.fromPlatform(super.getById(id));
    }

    @Override
    public PlatformEntity getPlatform(SiPlatIdFind info) {
        return uniPlatformSingleAssembler.fromPlatform(
                super.lambdaQuery()
                        .eq(PlatformPO::getId, info.getPlatformId())
                        .eq(null != info.getState(), PlatformPO::getState, info.getState())
                        .one());
    }

    @Override
    public PlatformEntity getPlatformByName(String name) {
        return uniPlatformSingleAssembler.fromPlatform(
                super.lambdaQuery()
                        .eq(PlatformPO::getName, name)
                        .one());
    }

    @Override
    public SiPageResult<SiPlatform> findPage(PlatPageInfo req) {
        if (StrUtil.isNotBlank(req.getUserId())) {
            return findPageAuth(req);
        } else {
            return findPageNoAuth(req);
        }
    }

    public SiPageResult<SiPlatform> findPageAuth(PlatPageInfo req) {
        Page<PlatformPO> page = new Page<>(req.getCurrent(), req.getPageSize());
        super.selectJoinListPage(page, PlatformPO.class, new MPJLambdaWrapper<PlatformPO>()
                .selectAll(PlatformPO.class)
                .innerJoin(AuthPlatformPO.class, AuthPlatformPO::getAuthPlatform, PlatformPO::getId)
                .like(StrUtil.isNotBlank(req.getName()), PlatformPO::getName, req.getName())
                .in(null != req.getPlatformIds() && !req.getPlatformIds().isEmpty(),
                        PlatformPO::getId, req.getPlatformIds())
                .eq(null != req.getState(), PlatformPO::getState, req.getState())
                .eq(AuthPlatformPO::getUserId, req.getUserId())
                .ge(StrUtil.isNotBlank(req.getStartTime()), PlatformPO::getCreateTime, req.getStartTime())
                .le(StrUtil.isNotBlank(req.getEndTime()), PlatformPO::getCreateTime, req.getEndTime())
                .orderByDesc(PlatformPO::getCreateTime));
        return PageUtil.convertPage(page, this::convertToPlatform);
    }

    public SiPageResult<SiPlatform> findPageNoAuth(PlatPageInfo req) {
        Page<PlatformPO> page = new Page<>(req.getCurrent(), req.getPageSize());
        page = super.lambdaQuery()
                .like(StrUtil.isNotBlank(req.getName()), PlatformPO::getName, req.getName())
                .in(null != req.getPlatformIds() && !req.getPlatformIds().isEmpty(),
                        PlatformPO::getId, req.getPlatformIds())
                .eq(null != req.getState(), PlatformPO::getState, req.getState())
                .ge(StrUtil.isNotBlank(req.getStartTime()), PlatformPO::getCreateTime, req.getStartTime())
                .le(StrUtil.isNotBlank(req.getEndTime()), PlatformPO::getCreateTime, req.getEndTime())
                .orderByDesc(PlatformPO::getCreateTime)
                .page(page);
        return PageUtil.convertPage(page, this::convertToPlatform);
    }

    public List<SiPlatform> convertToPlatform(List<PlatformPO> plList) {
        List<SiPlatform> targetPl = new ArrayList<>();

        plList.forEach(item -> {
            SiPlatform plItem = new SiPlatform();
            plItem.setId(item.getId());
            plItem.setProviderId(item.getProviderId());
            plItem.setProviderName(item.getName());
            plItem.setName(item.getName());
            plItem.setState(item.getState());
            plItem.setSecret(item.getSecret());
            plItem.setRealmId(item.getRealmId());
            plItem.setHomeUrl(item.getHomeUrl());
            plItem.setTicketUrl(item.getTicketUrl());
            plItem.setUpdateTime(item.getUpdateTime());
            plItem.setCreateTime(item.getCreateTime());
            targetPl.add(plItem);
        });

        return targetPl;
    }
}
